from flask import Flask, request, jsonify, g, current_app, session
from flask_jwt_extended import (
    JWTManager,
    get_jwt_identity,
    verify_jwt_in_request,
)
from flask_jwt_extended.exceptions import NoAuthorizationError, InvalidHeaderError, WrongTokenError, RevokedTokenError, \
    FreshTokenRequired

from config import Config
from extension import db

app = Flask(__name__)
app.config.from_object(Config)  # 加载配置

# 修改变量标签（默认 {{ }} → [[ ]]）
app.jinja_env.variable_start_string = '[[ '
app.jinja_env.variable_end_string = ' ]]'

# 初始化扩展
db.init_app(app)
jwt = JWTManager(app)

from routes.page import api_bp as page_bp
from routes.auth import api_bp as auth_bp
from routes.student import api_bp as student_bp
from routes.teacher import api_bp as teacher_bp
from routes.course import api_bp as course_bp
from routes.score import api_bp as score_bp
from routes.clazz import api_bp as class_bp

app.register_blueprint(page_bp)
app.register_blueprint(auth_bp)
app.register_blueprint(student_bp)
app.register_blueprint(teacher_bp)
app.register_blueprint(course_bp)
app.register_blueprint(score_bp)
app.register_blueprint(class_bp)


@app.before_request
def verify_token():
    # 不需要拦截的路由
    exclude_routes = ['/login', '/register', '/', '/static', '/favicon.ico']
    if request.path in exclude_routes or request.path.startswith('/static'):
        return

    try:
        # 优先从请求头中获取token
        auth_header = request.headers.get('Authorization')
        if auth_header and auth_header.startswith('Bearer '):
            token = auth_header.split(' ')[1]
        else:
            # 从Session中获取token
            token = session.get('token')
            if not token:
                raise NoAuthorizationError("缺少认证 Token")

        # 手动验证JWT Token
        from flask_jwt_extended import decode_token
        data = decode_token(token)

        # 获取用户身份
        user_id = data['sub']
        g.current_user = {
            'id': user_id
        }

    except NoAuthorizationError:
        return jsonify({'code': 401, 'msg': '缺少认证 Token'}), 401
    except Exception as e:
        current_app.logger.error(f"Token 验证失败: {str(e)}", exc_info=True)
        return jsonify({'code': 500, 'msg': '认证服务异常'}), 500

# 开发环境自动创建表（生产环境用迁移工具）
if __name__ == '__main__':
    with app.app_context():
        if app.config['DEBUG']:
            db.create_all()
    app.run(host='0.0.0.0', port=5000, debug=app.config['DEBUG'])
